package net.yambal.RTM.Method
{
	import flash.events.EventDispatcher;
	
	import net.yambal.RTM.Event.NoteEvent;
	import net.yambal.RTM.Event.RestErrorEvent;
	import net.yambal.RTM.Event.RestEvent;
	import net.yambal.RTM.Event.TasksEvent;
	import net.yambal.RTM.Event.TimelineEvent;
	import net.yambal.RTM.Items.RTMList;
	import net.yambal.RTM.Items.RTMLocation;
	import net.yambal.RTM.Items.RTMTaskSeries;
	import net.yambal.RTM.Items.RTMTransaction;
	import net.yambal.RTM.RestWrapper.RestManager;
	import net.yambal.RTM.RestWrapper.RestService;
	import net.yambal.RTM.Utilty.Parser;
	import net.yambal.RTM.Utilty.RTMBooleanUtil;
	import net.yambal.RTM.Utilty.RTMDateUtil;
	import net.yambal.RTM.Utilty.RTMTimelineGetter;
	
	[Event(name="get_list", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="add_task", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="set_name", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="add_tags", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="set_tags", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="remove_tags", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="complete", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="set_priority", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="move_priority", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="move_to", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="postpone", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="delete_tag", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="set_estimate", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="set_recurrence", type="net.yambal.RTM.Event.TasksEvent")]
	[Event(name="set_location", type="net.yambal.RTM.Event.TasksEvent")]
	
	[Event(name="add_note", type="net.yambal.RTM.Event.NoteEvent")]
	[Event(name="edit_note", type="net.yambal.RTM.Event.NoteEvent")]
	[Event(name="delete_note", type="net.yambal.RTM.Event.NoteEvent")]
	public class Tasks extends EventDispatcher
	{
		
		public var notes:Notes = new Notes();
		
		public function Tasks()
		{
			this.notes.addEventListener(NoteEvent.ADD, this.NoteEventRelay);
			this.notes.addEventListener(NoteEvent.EDIT, this.NoteEventRelay);
			this.notes.addEventListener(NoteEvent.DELETE, this.NoteEventRelay);
		}
		
		private function NoteEventRelay(e:NoteEvent):void{
			this.dispatchEvent(new NoteEvent(e.type, e.bubbles, e.cancelable, e.notes, e.transaction));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * タスク一覧を取得する
		 **/
		public function getList(api_key:String, shared_secret:String, auth_token:String, list:RTMList = null, filter:String = null, last_sync:Date = null):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			if(list){
				p.list_id = list.id;
			}
			if(filter){
				p.filter = filter;
			}
			if(last_sync){
				p.last_sync = last_sync;
			}
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_GET_LIST, p, this.onGetList, this.onFaultGetList, false, shared_secret);
		}
		
		private function onFaultGetList(code:Number, massage:String, ro:Object):void{
			trace(code);
			trace(massage);
		}
		
		private function onGetList(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var res:Array = Parser.TaskSeriesXMLListToTaskSeries(result_xml.descendants("taskseries"));
			this.dispatchEvent(new TasksEvent(TasksEvent.GET_LIST, res));
		}

		// ---------------------------------------------------------------------------
		/**
		 * Add:タスクを追加する
		 **/
		public function add(api_key:String, shared_secret:String, auth_token:String, name:String, list:RTMList = null, parse:String = null):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.name = name;
			if(list){
				p.list_id = list.id;
			}
			if(parse && parse.length != 0){
				p.parse = parse;
			}
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_ADD, p, this.onAdd, this.onFaultAdd, true, shared_secret, "タスクの追加");
		}
		
		private function onFaultAdd(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onAdd(result_xml:XML, ro:Object, t:RTMTransaction):void{		
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.ADD_TASK,null,ts, t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * setName:タスク名称を変更する
		 **/
		public function setName(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, name:String):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.name = name;
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_NAME, p, this.onSetName, this.onFaultSetName, true, shared_secret, "タスク名称を変更する");
		}
		
		private function onFaultSetName(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onSetName(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(XMLList(result_xml.descendants("taskseries"))[0]);
			var list_id:uint = result_xml.list.@id;
			this.dispatchEvent(new TasksEvent(TasksEvent.SET_NAME,null,ts, t));
		}
		
		
		// ---------------------------------------------------------------------------
		/**
		 * addTags
		 **/
		public function addTags(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, tags:Array):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.tags = tags.join(",");
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_ADDTAGS, p, this.onAddTags, this.onFaultAddTags, true, shared_secret, "タグの追加");
		}		
		
		private function onFaultAddTags(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onAddTags(result_xml:XML, ro:Object, t:RTMTransaction):void{	
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(XMLList(result_xml.descendants("taskseries"))[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.ADD_TAGS, null, ts, t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * setTags
		 **/
		public function setTags(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, tags:Array):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.tags = tags.join(",");
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_TAGS, p, this.onSetTags, this.onFaultSetTags, true, shared_secret, "タグのセット");
		}
		
		private function onFaultSetTags(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onSetTags(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(XMLList(result_xml.descendants("taskseries"))[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.SET_TAGS, null, ts, t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * removeTags
		 **/
		public function removeTags(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, tags:Array):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.tags = tags.join(",");
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_TAGS, p, this.onRemoveTags, this.onFaultRemoveTags, true, shared_secret, "タグの削除");
		}
		
		private function onFaultRemoveTags(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onRemoveTags(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(XMLList(result_xml.descendants("taskseries"))[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.REMOVE_TAGS, null, ts, t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * complete
		 **/
		public function complete(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;

			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_COMPLETE, p, this.onComplete, this.onFaultComplete, true, shared_secret, "完了");
		}
		
		private function onFaultComplete(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onComplete(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.COMPLETE,null,ts,t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * uncomplete
		 **/
		public function uncomplete(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;

			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_UNCOMPLETE, p, this.onUnComplete, this.onFaultUnComplete, true, shared_secret, "タスクを未完了");
		}
		
		private function onFaultUnComplete(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onUnComplete(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.UNCOMPLETE,null,ts,t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * setPriority
		 **/
		public function setPriority(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, priority:int):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;
			p.priority = priority;

			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_PRIORITY, p, this.onSetPriority, this.onFaultSetPriority, true, shared_secret, "重要度をセット");
		}
		
		private function onFaultSetPriority(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onSetPriority(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.SET_PRIORITY,null,ts,t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * movePriority
		 **/
		public function movePriority(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, up_or_down:String):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;
			p.direction = up_or_down;

			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_MOVE_PRIORITY, p, this.onMovePriority, this.onFaultMovePriority, true, shared_secret, "重要度を変更");
		}
		
		private function onFaultMovePriority(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onMovePriority(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.MOVE_PRIORITY,null,ts,t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * moveTo
		 **/
		public function moveTo(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, from_list:RTMList, to_list:RTMList):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;
			p.from_list_id = from_list.id;
			p.to_list_id = to_list.id;

			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_NOVE_TO, p, this.onMoveTo, this.onFaultMoveTo, true, shared_secret, "移動");
		}

		
		private function onFaultMoveTo(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onMoveTo(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.MOVE_TO,null,ts,t));
		}
	
		// ---------------------------------------------------------------------------
		/**
		 * 延期する
		 **/
		public function postpone(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.task_id = task_series.task.id;
			p.taskseries_id = task_series.id;

			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_POSTPONE, p, this.onPostpone, this.onFaultPostpone, true, shared_secret, "延期");
		}
		
		private function onFaultPostpone(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onPostpone(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.POSTPONE,null,ts,t));
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * 満期日？
		 * 仕事の満期日を決めます。
		 * 与えられるべきものが提供されないならば、どんな既存の満期日でもセットされません。
		 * has_due_time(満期日にそれ相当の時間があるかどうか指定します)が提供されるならば、満期日は一体となって時間という特徴があります。
		 * もしもは、解析します1の価値を持って、rtm.time.parseに従って真解析されます。
		 **/
		public function setDueDate(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, due:Date = null, parse:String = null, is_set_has_due_time_flg:Boolean = false, has_due_time:Boolean = true):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.taskseries_id = task_series.id;
			p.task_id = task_series.task.id;
			if(due != null){
				p.due = RTMDateUtil.to8601(due);
				trace("\tdue:" + p.due);
			}
			if(is_set_has_due_time_flg){
				p.has_due_time = RTMBooleanUtil.toRTMBoolean(has_due_time);
				trace("\thas_due_time:" + p.has_due_time);
			}
			if(parse){
				p.parse = parse;
				trace("\tparse:" + p.parse);
			}
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_DUE_DATE, p, this.onSetDueDate, this.onFaultSetDueDate, true, shared_secret, "期日のセット");
		}
		
		private function onFaultSetDueDate(code:Number, massage:String, ro:Object):void{
			trace(code);
			trace(massage);
		}
		
		private function onSetDueDate(result_xml:XML, ro:Object, t:RTMTransaction):void{
			trace(result_xml);
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * 場所
		 **/
		public function setLocation(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, location:RTMLocation = null):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.taskseries_id = task_series.id;
			p.task_id = task_series.task.id;
			p.location_id = location.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_LOCATION, p, this.onSetLocation, this.onFaultSetLocation, true, shared_secret, "場所のセット");
		}
		
		private function onFaultSetLocation(code:Number, massage:String, ro:Object):void{
			trace(code);
			trace(massage);
		}
		
		private function onSetLocation(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			var list_id:uint = result_xml.list.@id;
			
			this.dispatchEvent(new TasksEvent(TasksEvent.SET_LOCATION,null,ts,t));
		}

		
		// ---------------------------------------------------------------------------
		/**
		 * 予測時間
		 **/
		public function setEstimate(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, estimate:String):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.estimate = estimate;
			p.list_id = task_series.list_id;
			p.taskseries_id = task_series.id;
			p.task_id = task_series.task.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_ESTIMATE, p, this.onSetEstimate, this.onFaultSetEstimate, true, shared_secret, "予測時間をセット");
		}
		
		private function onFaultSetEstimate(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onSetEstimate(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.SET_ESTIMATE, null,ts,t))
		}

		// ---------------------------------------------------------------------------
		/**
		 * リピート
		 **/
		public function setRecurrence(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, repeat:String):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.repeat = repeat;
			p.list_id = task_series.list_id;
			p.taskseries_id = task_series.id;
			p.task_id = task_series.task.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_ESTIMATE, p, this.onSetRecurrence, this.onFaultSetRecurrence, true, shared_secret, "リピートをセット");
		}
		
		private function onFaultSetRecurrence(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onSetRecurrence(result_xml:XML, ro:Object, t:RTMTransaction):void{		
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.SET_RECURRENCE, null,ts,t))
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * URL
		 **/
		public function setURL(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries, url:String):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.url = url;
			p.list_id = task_series.list_id;
			p.taskseries_id = task_series.id;
			p.task_id = task_series.task.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_SET_URL, p, this.onSetUrl, this.onFaultSetUrl, true, shared_secret, "URLをセット");
		}
		
		private function onFaultSetUrl(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onSetUrl(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.SET_URL, null,ts,t))
		}
		
		// ---------------------------------------------------------------------------
		/**
		 * タスクを削除する
		 **/
		public function deleteTask(api_key:String, shared_secret:String, auth_token:String, task_series:RTMTaskSeries):void{
			var p:Object = new Object();
			p.api_key = api_key;
			p.auth_token = auth_token;
			p.list_id = task_series.list_id;
			p.taskseries_id = task_series.id;
			p.task_id = task_series.task.id;
			
			var RM:RestManager = new RestManager();
			RM.doMethod(RestService.METHOD_TASKS_DELETE_TASK, p, this.onSetUrl, this.onFaultSetUrl, true, shared_secret, "削除");
		}
		
		private function onFaultDeleteTask(code:Number, massage:String, ro:Object):void{		
			trace(code);
			trace(massage);
		}
		
		private function onDeleteTask(result_xml:XML, ro:Object, t:RTMTransaction):void{
			var tsx:XMLList = result_xml.descendants("taskseries");
			var ts:RTMTaskSeries = Parser.TaskSeriesXMLToTaskSeries(tsx[0]);
			this.dispatchEvent(new TasksEvent(TasksEvent.DELETE_TAG, null,ts,t));
		}
		// ---------------------------------------------------------------------------
	}
}